import router from './router'
import type { RouteRecordRaw } from 'vue-router'
import { isRelogin } from '@/config/axios/service'
import {
  getAccessToken,
  setTenantId,
  setToken,
  getSSOFlag,
  setSSOFlag,
  setssoToken,
  setUserId
} from '@/utils/auth'
import { isIP } from './utils/is'
import { useTitle } from '@/hooks/web/useTitle'
import { useNProgress } from '@/hooks/web/useNProgress'
import { usePageLoading } from '@/hooks/web/usePageLoading'
import { useDictStoreWithOut } from '@/store/modules/dict'
import { useUserStoreWithOut } from '@/store/modules/user'
import { usePermissionStoreWithOut } from '@/store/modules/permission'
import * as LoginApi from '@/api/login'
import _sso from './sso'
import { ElMessage, ElMessageBox, ElLoading } from 'element-plus'

// 获取所有字典
const dictStore = useDictStoreWithOut() //字典store
const userStore = useUserStoreWithOut() //账户store

const { start, done } = useNProgress()

const { loadStart, loadDone } = usePageLoading()

const parseURL = (
  url: string | null | undefined
): { basePath: string; paramsObject: { [key: string]: string } } => {
  // 如果输入为 null 或 undefined，返回空字符串和空对象
  if (url == null) {
    return { basePath: '', paramsObject: {} }
  }

  // 找到问号 (?) 的位置，它之前是基础路径，之后是查询参数
  const questionMarkIndex = url.indexOf('?')
  let basePath = url
  const paramsObject: { [key: string]: string } = {}

  // 如果找到了问号，说明有查询参数
  if (questionMarkIndex !== -1) {
    // 获取 basePath
    basePath = url.substring(0, questionMarkIndex)

    // 从 URL 中获取查询字符串部分
    const queryString = url.substring(questionMarkIndex + 1)

    // 使用 URLSearchParams 遍历参数
    const searchParams = new URLSearchParams(queryString)
    searchParams.forEach((value, key) => {
      // 封装进 paramsObject 对象
      paramsObject[key] = value
    })
  }

  // 返回 basePath 和 paramsObject
  return { basePath, paramsObject }
}

// 路由不重定向白名单
const whiteList = [
  '/login',
  '/social-login',
  '/auth-redirect',
  '/bind',
  '/register',
  '/oauthLogin/gitee',
  '/apihub',
  '/apidoc'
]
window.addEventListener('message', async (e) => {
  const data = e.data
  if (data.type == 'ssoauth') {
    if (location.hash.indexOf('apihub') !== -1 || location.hash.indexOf('apidoc') !== -1) {
      return
    }
    // 防止在别处已经登出sso,仍可进入系统
    if (
      !data.message.Success &&
      location.hash.indexOf('login') == -1 &&
      !isRelogin.show &&
      (getSSOFlag() || location.hash.indexOf('ssoCheck') != -1)
    ) {
      ElMessage.warning('SSO认证失效，退出中！')
      userStore.loginOut()
      _sso.logout()
    } else if (
      !data.message.Success &&
      location.hash.indexOf('login') == -1 &&
      !isRelogin.show &&
      (!getSSOFlag() || location.hash.indexOf('ssoCheck') == -1)
    ) {
      console.log('SSO认证失效，退出到系统登录页面')
      router.push({ path: '/login' })
    }
  }
})
// 检测是否为sso登录
async function checkSSOAuthStatus() {
  return new Promise((resolve, reject) => {
    // 监听认证状态变化
    _sso.on('auth', async (authResult) => {
      console.log('auth回调', authResult)
      if (authResult.Success && !getAccessToken()) {
        setTenantId('1')
        setSSOFlag(true)
        setssoToken(authResult.Data.accessToken)
        LoginApi.ssoLogin({ accessToken: authResult.Data.accessToken })
          .then(async (res) => {
            setToken(res)
            setTenantId(res.tenantId)
            setUserId(res.userId)
            console.log('auth回调认证成功')
            resolve('success') // 认证成功
            // 屏蔽工作台初始化
            /*if (!res.hasPrivateToken) {
              const loadingInstance = ElLoading.service({
                text: '工作台初始化中，请稍后...'
              })
              try {
                await LoginApi.initPrivateToken({ accessToken: authResult.Data.accessToken })
              } catch (error) {
                console.log('initPrivateToken接口错误', error)
              } finally {
                loadingInstance.close()
              }
            }*/
          })
          .catch((error) => {
            console.log('登录接口错误', error)
            resolve('login fail') // 认证失败
          })
      } else {
        resolve('sso fail') // 认证失败
      }
    })
    // 设置超时，防止无限等待
    setTimeout(() => {
      reject(new Error('SSO认证状态检查超时'))
    }, 30000)
  })
}
// 创建一个队列来保存待处理的导航请求
let pendingNavigations = [];
// 添加全局监听，提高sso验证速度
_sso.on('auth', async (authResult) => {
  console.log('全局auth回调', authResult)
  if (location.href.indexOf('ssoCheck') != -1 && getAccessToken()) {
    setSSOFlag(true)
    userStore.loginOut()
  }
  if (authResult.Success && !getAccessToken()) {
    setTenantId('1')
    setSSOFlag(true)
    setssoToken(authResult.Data.accessToken)
    try {
      const res = await LoginApi.ssoLogin({ accessToken: authResult.Data.accessToken })
      setToken(res)
      setTenantId(res.tenantId)
      setUserId(res.userId)
      console.log('全局auth认证成功')
      // if (!res.hasPrivateToken) {
      //   const loadingInstance = ElLoading.service({
      //     text: '工作台初始化中，请稍后...'
      //   })
      //   try {
      //     await LoginApi.initPrivateToken({ accessToken: authResult.Data.accessToken })
      //   } catch (error) {
      //     console.log('initPrivateToken接口错误', error)
      //   } finally {
      //     loadingInstance.close()
      //   }
      // }
      processPendingNavigations()
    } catch (error) {
      console.log('sso登录接口错误', error)
    }
  }
})
// 根据保存的to对象进行跳转
function processPendingNavigations() {
  if (pendingNavigations.length > 0) {
    const to = pendingNavigations.shift();
    if (to) {
      console.log('全局auth认证后跳转', to)
      router.push({ path: to.path });
    }
  } else {
    router.push({ path: '/' });
  }
}
// sso退出回调
_sso.on('logout', async () => {
  console.log('logout回调')
  // 重置标识
  setSSOFlag(false)
  setTimeout(() => {
    if (isIP(location.hostname)) {
      window.location.href = import.meta.env.VITE_BACK_IP
    } else {
      window.location.href = import.meta.env.VITE_BACK_URL
    }
  }, 500)
})

// 路由加载前
router.beforeEach(async (to, from, next) => {
  start()
  loadStart()
  const shouldCheckSSO = to.query.ssoCheck == 'true'
  // 存储跳转链接
  if (shouldCheckSSO) {
    pendingNavigations = []
    pendingNavigations.push(to)
  }
  // 清空用户信息，保证每次进入工作台都是最新登录的账号
  if (shouldCheckSSO && getAccessToken()) {
    setSSOFlag(true)
    userStore.loginOut()
    next({ path: to.path })
  } else if (getAccessToken()) {
    if (to.path === '/login') {
      next({ path: '/' })
    } else {
      const permissionStore = usePermissionStoreWithOut() // 权限store
      if (!dictStore.getIsSetDict) {
        //字典是否有数据
        await dictStore.setDictMap() //处理字典数据
      }
      if (!userStore.getIsSetUser) {
        //是否有用户信息数据
        isRelogin.show = true
        await userStore.setUserInfoAction(to.path) //处理用户信息数据
        isRelogin.show = false
        // 后端过滤菜单
        await permissionStore.generateRoutes()
        permissionStore.getAddRouters.forEach((route) => {
          router.addRoute(route as unknown as RouteRecordRaw) // 动态添加可访问路由表
        })
        const redirectPath = from.query.redirect || to.path
        // 修复跳转时不带参数的问题
        const redirect = decodeURIComponent(redirectPath as string)
        const { basePath, paramsObject: query } = parseURL(redirect)
        const nextData = to.path === redirect ? { ...to, replace: true } : { path: redirect, query }
        next(nextData)
      } else {
        next()
      }
    }
  } else {
    if (whiteList.indexOf(to.path) !== -1) {
      next()
    } else {
      try {
        // 等待认证状态检查完成
        const isAuthenticated = (await checkSSOAuthStatus()) as any
        if (isAuthenticated.indexOf('success') != -1) {
          next(to.path)
        } else if (isAuthenticated.indexOf('login') != -1) {
          handleFailer(to, next, '登录接口异常，请重新登录！')
        } else {
          handleFailer(to, next, 'SSO认证失败，请重新登录！')
        }
      } catch (error) {
        // ElMessage.warning('SSO认证超时，正在重新加载！')
        if (location.href.indexOf('ssoCheck') != -1) {
          location.reload()
        }
      }
    }
  }
})

const handleFailer = (to, next, message) => {
  if (getSSOFlag()) {
    isRelogin.show = true
    ElMessageBox.confirm(message, '系统提示', {
      showCancelButton: false,
      closeOnClickModal: false,
      showClose: false,
      confirmButtonText: '重新登录',
      type: 'warning'
    }).then(() => {
      isRelogin.show = false
      _sso.logout()
    })
  } else {
    next({ path: '/login' })
  }
}

router.afterEach((to) => {
  useTitle(to?.meta?.title as string)
  done() // 结束Progress
  loadDone()
})
